package com.kefu.call.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kefu.basic.model.BasicMsg;
import com.kefu.call.mapper.ActivityBaseInfoMapper;
import com.kefu.call.mapper.ActivityInventoryInfoMapper;
import com.kefu.call.mapper.CallMakeCallMapper;
import com.kefu.call.model.ActivityBaseInfo;
import com.kefu.call.model.ActivityInventoryInfo;
import com.kefu.call.vo.*;
import com.kefu.call.vo.ActivityInventoryInfoAssignmentVo.AssignmentUserVo;
import com.kefu.common.context.KefuContext;
import com.kefu.common.exception.BusinessException;
import com.kefu.common.mybatis.Order;
import com.kefu.common.result.Result;
import com.kefu.common.result.ResultGenerator;
import com.kefu.common.service.AbstractKefuService;
import com.kefu.common.util.BigDecimalUtil;
import com.kefu.common.util.JacksonUtil;
import com.kefu.common.util.StreamUtil;
import com.kefu.common.vo.BatchVo;
import com.kefu.common.vo.DetailVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class ActivityInventoryInfoService extends AbstractKefuService<ActivityInventoryInfo> {
	@Resource
	protected ActivityBaseInfoMapper activityBaseInfoMapper;
	@Resource
	protected CallMakeCallMapper callMakeCallMapper;
	@Resource
	protected ActivityInventoryInfoMapper activityInventoryInfoMapper;

	@Transactional
    public void save(List<ActivityInventoryInfo> list) {
		list.forEach(info->{
			ActivityInventoryInfo activityInventoryInfo = activityInventoryInfoMapper.selectOne(info);
			if (activityInventoryInfo==null){
			activityInventoryInfoMapper.insert(info);
			}
		});
    }

	@Transactional
	public String handle(ActivityInventoryInfoHandleVo handleVo){
		ActivityInventoryInfo info = handleVo.convert();
		activityInventoryInfoMapper.updateByPrimaryKeySelective(info);
		return info.getActivityId();

	}

	@Transactional
	public ActivityInventoryInfo preHandel(String id) {
		ActivityInventoryInfo info=activityInventoryInfoMapper.selectByPrimaryKey(id);
		if(info==null) {
			throw BusinessException.msg("清单不存在");
		}
		KefuContext context = KefuContext.getKefuContext();
	    boolean update=false;
		if(info.getAssignmentStatus()==1) {//未分配
			info.setUserId(context.getUserId());
			info.setUserName(context.getUserName());
			info.setAssignmentStatus(2);
			update=false;
		}
		if(info.getAssignmentStatus()==2) {
			if(!context.getUserId().equals(info.getUserId())) {
				throw BusinessException.msg("该清单已经被分配");
			}
			//info.setInventoryStatus(3);//处理中
			info.setUpdateTime(context.getNow());
			info.setUpdateUser(context.getUserId());
			update=false;
		}
		if(info.getInventoryStatus()==2) {
			throw BusinessException.msg("呼叫清单已经处理完成");
		}

		if(update) {
			activityInventoryInfoMapper.updateByPrimaryKeySelective(info);
		}

		return info;
	}

	@Transactional
	public ActivityInventoryInfoAssignmentVo.AssignmentResultVo assignment(ActivityInventoryInfoAssignmentVo assignmentVo){
		if(assignmentVo.getAssignmentType() ==1 ) {
			ActivityInventoryInfoAssignmentVo.SimpleAssignmentVo vo = assignmentVo.getSimpleAssignment();
			if (Objects.isNull(vo)) {
				throw BusinessException.msg("分配数据异常");
			}
			List<ActivityInventoryInfo> list = activityInventoryInfoMapper.selectByIdList(vo.getInventoryIds());
			return assignment(vo.getUsers(), list);
		}
		if(assignmentVo.getAssignmentType()==2){
			ActivityInventoryInfoAssignmentVo.AdvancedAssignmentVo vo = assignmentVo.getAdvancedAssignment();
			if (Objects.isNull(vo)) {
				throw BusinessException.msg("分配数据异常");
			}
			Page<ActivityInventoryInfo> page = new Page<>(assignmentVo.getAdvancedAssignment().getPageNo(), assignmentVo.getAdvancedAssignment().getPageSize(), false);
			List<ActivityInventoryInfo> list = activityInventoryInfoMapper.selectPage(page,assignmentVo.getAdvancedAssignment().getExample()).getRecords();
			return assignment(vo.getUsers(), list);
		}
		return null;
	}

	@Transactional
	public List<String> recovery(ActivityInventoryInfoRecoveryVo recoveryVo){
		List<String> message=Lists.newArrayList();
		if(recoveryVo.getRecoveryType()==1) {
			Optional.ofNullable(recoveryVo.getSimpleRecovery())
			.ifPresent(simpleRecovery->{
				List<ActivityInventoryInfo> list=activityInventoryInfoMapper.selectByIdList(simpleRecovery.getInventoryIds());
				message.addAll(recovery(list));
			});

		}else if(recoveryVo.getRecoveryType()==2){
			Optional.ofNullable(recoveryVo.getAdvancedRecovery())
			.ifPresent(advancedRecovery->{
				List<ActivityInventoryInfo> list=activityInventoryInfoMapper.selectList(recoveryVo.getAdvancedRecovery().getExample());
				message.addAll(recovery(list));
			});
		}

		return message;
	}

	private List<String> recovery(List<ActivityInventoryInfo> list) {
		List<String> message=Lists.newArrayList();
		KefuContext context=KefuContext.getKefuContext();
		String tenantId=context.getTenantId();
		AtomicInteger recoverytNum=new AtomicInteger();
		StreamUtil.stream(list)
		 	.forEach(info->{
 				if(!tenantId.equals(info.getTenantId())) {
 					String msg=String.format("清单%s(%s)属于租户%s，与当前租户%s不符，跳过", info.getInventoryName(),info.getInventoryId(),info.getTenantId(),tenantId);
 					message.add(msg);
 					logger.warn(msg);
 					return;
 				}
 				if(info.getDataStatus()==0) {
 					String msg=String.format("清单%s(%s)数据状态错误%s，跳过", info.getInventoryName(),info.getInventoryId(),info.getDataStatus());
 					message.add(msg);
 					logger.warn(msg);
 					return;
 				}
 				if(info.getInventoryStatus()==2) {//只有 已分配，处理中得清单可以回收 2已分配，3处理中
 					String msg=String.format("清单%s(%s)已经分配给%s(%s),状态为%s,不支持回收，跳过",info.getInventoryName(),info.getInventoryId(),info.getUserName(),info.getUserId(),info.getInventoryStatus());
 					message.add(msg);
 					logger.warn(msg);
 					return;
 				}
 				String msg=String.format("回收清单%s(%s)之前分配给%s(%s)",info.getInventoryName(),info.getInventoryId(),info.getUserName(),info.getUserId());
 				logger.info(msg);
 				LambdaUpdateWrapper<ActivityInventoryInfo> updateWrapper=new LambdaUpdateWrapper<>();
 				updateWrapper.set(ActivityInventoryInfo::getUserId, null);
 				updateWrapper.set(ActivityInventoryInfo::getUserName, null);
 				updateWrapper.set(ActivityInventoryInfo::getAssignmentStatus, 1);
 				updateWrapper.eq(ActivityInventoryInfo::getInventoryId, info.getInventoryId());
 				activityInventoryInfoMapper.update(null, updateWrapper);

 				recoverytNum.incrementAndGet();
		 	});
		 String msg=String.format("总共回收了%d条清单",recoverytNum.get());
		 message.add(msg);
		 logger.info(msg);
		 return message;
	}

	private ActivityInventoryInfoAssignmentVo.AssignmentResultVo assignment(List<AssignmentUserVo> users, List<ActivityInventoryInfo> list){
		List<String> message = Lists.newArrayList();
		List<ActivityInventoryInfo> assignments = Lists.newArrayList();
		Iterator<ActivityInventoryInfo> iterator = list.iterator();
		for (AssignmentUserVo user : users) {
			int number = user.getNumber();
			int assignmentNum = 0;
			while(number > 0 && iterator.hasNext()) {
				ActivityInventoryInfo info = iterator.next();
				if(!KefuContext.getTid().equals(info.getTenantId())) {
					String msg = String.format("清单%s(%s)属于租户%s，与当前租户%s不符，跳过", info.getInventoryName(),info.getInventoryId(),info.getTenantId(), KefuContext.getTid());
					message.add(msg);
					logger.warn(msg);
					continue;
				}
				if(info.getDataStatus()==0) {
					String msg=String.format("清单%s(%s)数据状态错误%s，跳过", info.getInventoryName(),info.getInventoryId(),info.getDataStatus());
					message.add(msg);
					logger.warn(msg);
					continue;
				}
				if(info.getAssignmentStatus()==2) {
					String msg=String.format("清单%s(%s)已经分配给%s(%s),跳过",info.getInventoryName(),info.getInventoryId(),info.getUserName(),info.getUserId());
					message.add(msg);
					logger.warn(msg);
					continue;
				}
				info.setUserId(user.getUserId());
				info.setUserName(user.getUserName());
				info.setAssignmentStatus(2);
				activityInventoryInfoMapper.updateByPrimaryKeySelective(info);
				assignments.add(info);
				number--;
				assignmentNum++;
			}
			String msg = String.format("为用户%s(%s)分配了%d条清单",user.getUserId(),user.getUserName(),assignmentNum);
			message.add(msg);
			logger.info(msg);
		}
		return ActivityInventoryInfoAssignmentVo.AssignmentResultVo.builder()
				.message(message).list(assignments).build();
	}

	@Transactional
	public int batchDelete(BatchVo batchVo) {
		try {
			if (batchVo.getIds().isEmpty()) {
				throw BusinessException.msg("请选择要删除的清单信息");
			}
			UpdateWrapper<ActivityInventoryInfo> wrapper = new UpdateWrapper<>();
			wrapper.lambda().in(ActivityInventoryInfo::getInventoryId, batchVo.getIds());
			ActivityInventoryInfo activityInventoryInfo = new ActivityInventoryInfo();
			activityInventoryInfo.setDataStatus(0);
			boolean flag = update(activityInventoryInfo, wrapper);
			logger.info("批量将活动清单数据状态置为0[{}]", flag, JacksonUtil.toString(batchVo));
			return flag ? 1 : 0;
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("删除拨打清单失败 : ", e);
		}
		return 0;
	}

	public Page<ActivityBaseInfo> myInventory(ActivityInventoryInfoMySearchVo param) {
		Page<ActivityBaseInfo> page = new Page<>(param.getPageNo(),param.getPageSize(),true);
		if(StringUtils.isNotBlank(param.getOrderField())) {
			if(param.getOrder()==Order.ASC) {
				page.addOrder(OrderItem.asc(StrUtil.toUnderlineCase(param.getOrderField())));
			}else {
				page.addOrder(OrderItem.descs(StrUtil.toUnderlineCase(param.getOrderField())));
			}
		}
		KefuContext kefuContext = KefuContext.getKefuContext();
		param.setUserId(kefuContext.getUserId());
		param.setTenantId(kefuContext.getTenantId());
		page = activityInventoryInfoMapper.myInventory(page, param);
		return page;
	}

	public ActivityBaseInfo myInventoryDetail(String id) {
		ActivityBaseInfo info = activityBaseInfoMapper.findById(id);
		LambdaQueryWrapper<ActivityInventoryInfo> wrapper = Wrappers.lambdaQuery(ActivityInventoryInfo.class);
		wrapper.eq(ActivityInventoryInfo::getActivityId, id);
		wrapper.eq(ActivityInventoryInfo::getUserId, KefuContext.getKefuContext().getUserId());
		return info;
	}

	@Transactional
	public void importDoc(InputStream inputStream, String activityId) {
		ActivityBaseInfo activityBaseInfo = activityBaseInfoMapper.selectByPrimaryKey(activityId);
		if (Objects.isNull(activityBaseInfo)) {
			return;
		}
		ExcelReader excelReader = ExcelUtil.getReader(inputStream);
		List<Map<String, Object>> list = excelReader.read(0, 1, 10000);
		List<ActivityInventoryInfo> dataList = Lists.newArrayList();
		KefuContext kefuContext = KefuContext.getKefuContext();
		for (Map<String, Object> map : list) {
			String customerName = String.valueOf(map.get("客户姓名"));
			String customerPhone = String.valueOf(map.get("客户电话"));
			if (StrUtil.isBlank(customerName)
					|| StrUtil.isBlank(customerPhone)
			|| "null".equals(customerName) || "null".equals(customerPhone)) {
				continue;
			}
			String inventoryName = String.valueOf(map.get("活动名称"));
			ActivityInventoryInfo info = new ActivityInventoryInfo();
			info.setInventoryId(IdUtil.simpleUUID());
			info.setActivityId(activityId);
			info.setInventoryName(StrUtil.isNotBlank(inventoryName) ? inventoryName : "导入客户拨打清单");
			info.setCreateUser(kefuContext.getUserId());
			info.setCreateTime(kefuContext.getNow());
			info.setUpdateUser(kefuContext.getUserId());
			info.setUpdateTime(kefuContext.getNow());
			info.setDataStatus(1);
			info.setTenantId(kefuContext.getTenantId());
			info.setInventoryStatus(1); // 未处理
			info.setIntentionStatus(0);
			info.setAssignmentStatus(1);
			info.setCustomerName(customerName);
			info.setCustomerPhone(customerPhone);
			info.setInventoryDesp("导入清单信息，生成清单拨打纪录！");
			dataList.add(info);
		}
		if (null != dataList && dataList.size() > 0) {
			save(dataList);
			logger.info("批量导入任务拨打清单信息 : {}", JacksonUtil.toString(dataList));
		}
	}

	public List<ActivityInventoryInfo> searchList(ActivityInventoryInfoSearchVo search) {
		List<ActivityInventoryInfo> list = activityInventoryInfoMapper.selectList(search.builder());
		return list;
	}

	public List<ActivityInventoryInfo> checkInventory(String id) {
		ActivityInventoryInfo info = activityInventoryInfoMapper.selectByPrimaryKey(id);
		if (Objects.isNull(info)) {
			throw BusinessException.msg("清单不存在");
		}
		String customerPhone = info.getCustomerPhone();
		List<ActivityInventoryInfo> list = activityInventoryInfoMapper.selectList(
				Wrappers.lambdaQuery(ActivityInventoryInfo.class).eq(ActivityInventoryInfo::getCustomerPhone, customerPhone).eq(ActivityInventoryInfo::getTenantId, KefuContext.getKefuContext().getTenantId()));
		logger.info("查询相同手机号下拨打清单纪录:{}", list);
		// 并且这个清单是分配给我的
		return list;
	}

	public ActivityInventoryStatisticsVo statistics(DetailVo search) {
		Map<String,Object> param=Maps.newHashMap();
		param.put("activityId", search.getId());
		ActivityInventoryStatisticsVo statisticsVo=activityInventoryInfoMapper.statisticsActivity(param);

		ActivityInventoryStatisticsVo statisticsVo2=callMakeCallMapper.statisticsActivity(param);
		statisticsVo2.setActivityId(search.getId());
		statisticsVo2.setInventoryCount(statisticsVo.getInventoryCount());
		statisticsVo2.setInventoryCompletedCount(statisticsVo.getInventoryCompletedCount());
		statisticsVo2.setInventoryUnCallCount(statisticsVo.getInventoryUnCallCount());
		statisticsVo2.setInventoryAvgTalkTime(BigDecimalUtil.decimals(statisticsVo2.getInventoryAvgTalkTime(),0));
		return statisticsVo2;
	}

	public List<ActivityUserInventoryStatisticsVo> statisticsUserInventory(DetailVo search) {
		Map<String,Object> param=Maps.newHashMap();
		param.put("activityId", search.getId());
		List<ActivityUserInventoryStatisticsVo> list=activityInventoryInfoMapper.statisticsUserInventory(param);
		List<ActivityUserInventoryStatisticsVo> list2=callMakeCallMapper.statisticsUserInventory(param);
		list.stream().forEach(statics->{
			list2.stream()
				.filter(statics2->statics2.getUserId().equals(statics.getUserId()))
				.findAny()
				.ifPresent(statics2->{
					statics.setInventoryCallCount(statics2.getInventoryCallCount());
					statics.setInventoryAnswerCount(statics2.getInventoryAnswerCount());
					statics.setUnAvailableCount(statics2.getUnAvailableCount());
					statics.setRingingSeatHangupCount(statics2.getRingingSeatHangupCount());
					statics.setRingingMissedCount(statics2.getRingingMissedCount());
				});
		});
		return list;
	}

	public ActivityInventoryStatisticsVo myStatistics(DetailVo detail) {
		Map<String,Object> param=Maps.newHashMap();
		param.put("userId", KefuContext.getKefuContext().getUserId());
		param.put("activityId", detail.getId());
		ActivityInventoryStatisticsVo statisticsVo=activityInventoryInfoMapper.statisticsActivity(param);

		ActivityInventoryStatisticsVo statisticsVo2=callMakeCallMapper.statisticsActivity(param);
		statisticsVo2.setInventoryCount(statisticsVo.getInventoryCount());
		statisticsVo2.setInventoryCompletedCount(statisticsVo.getInventoryCompletedCount());
		statisticsVo2.setInventoryUnCallCount(statisticsVo.getInventoryUnCallCount());
		statisticsVo2.setInventoryAvgTalkTime(BigDecimalUtil.decimals(statisticsVo2.getInventoryAvgTalkTime(),0));
		return statisticsVo2;
	}

	public Page<ActivityInventoryInfo> myInventoryList(ActivityMyInventoryInfoSearchVo search) {
		return super.search(search);
	}

	public void makeCall(DetailVo detailVo) {
		ActivityInventoryInfo info = activityInventoryInfoMapper.selectById(detailVo.getId());
		if(info==null) {
			throw BusinessException.msg("呼叫清单不存在");
		}
		if(info.getDataStatus()!=1) {
			throw BusinessException.msg("呼叫清单已删除");
		}
		if(info.getInventoryStatus()!=1) {
			throw BusinessException.msg("呼叫清单已经处理完成");
		}
		info.setCallCount(info.getCallCount()==null?1:info.getCallCount()+1);
		KefuContext context=KefuContext.getKefuContext();
		info.setUpdateTime(context.getNow());
		info.setUpdateUser(context.getUserId());
		activityInventoryInfoMapper.updateByPrimaryKeySelective(info);
	}

	public Page<ActivityInventoryInfo> listInventory(ActivityInventoryInfoSearchVo search) {
		Page<ActivityInventoryInfo> list = search(search);
		if (null != list && list.getRecords() != null && list.getRecords().size() > 0) {
			List<ActivityBaseInfo> activityBaseInfos = activityBaseInfoMapper.selectList(Wrappers.lambdaQuery(ActivityBaseInfo.class).eq(ActivityBaseInfo::getTenantId,
					KefuContext.getKefuContext().getTenantId()));
			Map<String, String> maps = activityBaseInfos.stream().collect(Collectors.toMap(ActivityBaseInfo::getActivityId, ActivityBaseInfo::getActivityName));
			list.getRecords().forEach(v -> {
				v.setActivityName(maps.get(v.getActivityId()));
			});
		}
		return list;
	}
	public String mergeInventory(Map<String, Object> vo) {

		return null;
	}
}
